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
34 import org.biojava.dasobert.dasregistry.DasSource;
\r
35 import org.biojava.dasobert.dasregistry.DasCoordinateSystem;
\r
37 public class FeatureSettings extends JPanel
\r
39 DasSourceBrowser dassourceBrowser;
\r
40 JPanel settingsPane = new JPanel();
\r
41 JPanel dasSettingsPane = new JPanel();
\r
43 final FeatureRenderer fr;
\r
44 final AlignFrame af;
\r
45 Object [][] originalData;
\r
46 final JInternalFrame frame;
\r
47 JScrollPane scrollPane = new JScrollPane();
\r
50 JSlider transparency = new JSlider();
\r
52 JPanel transPanel = new JPanel(new FlowLayout());
\r
53 boolean alignmentHasFeatures = false;
\r
55 public FeatureSettings(AlignFrame af)
\r
58 fr = af.getFeatureRenderer();
\r
60 transparency.setMaximum( 100 - (int)(fr.transparency*100) ) ;
\r
66 catch (Exception ex)
\r
68 ex.printStackTrace();
\r
71 dassourceBrowser = new DasSourceBrowser();
\r
72 dasSettingsPane.add(dassourceBrowser, BorderLayout.CENTER);
\r
76 if (af.getViewport().featuresDisplayed == null || fr.renderOrder==null)
\r
77 fr.findAllFeatures();
\r
82 frame = new JInternalFrame();
\r
83 frame.setContentPane(this);
\r
84 Desktop.addInternalFrame(frame, "Sequence Feature Settings", 400, 450);
\r
85 frame.setLayer(JLayeredPane.PALETTE_LAYER);
\r
88 public void setTableData()
\r
90 alignmentHasFeatures = false;
\r
92 if (fr.featureGroups == null)
\r
93 fr.featureGroups = new Hashtable();
\r
95 Vector allFeatures = new Vector();
\r
96 Vector allGroups = new Vector();
\r
97 SequenceFeature[] tmpfeatures;
\r
100 for (int i = 0; i < af.getViewport().alignment.getHeight(); i++)
\r
102 if (af.getViewport().alignment.getSequenceAt(i).getDatasetSequence().getSequenceFeatures() == null)
\r
105 alignmentHasFeatures = true;
\r
107 tmpfeatures = af.getViewport().alignment.getSequenceAt(i).getDatasetSequence().getSequenceFeatures();
\r
110 while (index < tmpfeatures.length)
\r
112 if(tmpfeatures[index].begin == 0 && tmpfeatures[index].end ==0)
\r
118 if(tmpfeatures[index].getFeatureGroup()!=null)
\r
120 group = tmpfeatures[index].featureGroup;
\r
121 if(!allGroups.contains(group))
\r
123 allGroups.addElement(group);
\r
125 boolean visible = true;
\r
126 if (fr.featureGroups.containsKey(group))
\r
128 visible = ( (Boolean) fr.featureGroups.get(group)).booleanValue();
\r
132 fr.featureGroups.put(group, new Boolean(visible));
\r
133 if (groupPanel == null)
\r
135 groupPanel = new JPanel();
\r
138 final JCheckBox check = new JCheckBox(group, visible);
\r
139 check.setFont(new Font("Serif", Font.BOLD, 12));
\r
140 check.addItemListener(new ItemListener()
\r
142 public void itemStateChanged(ItemEvent evt)
\r
144 fr.featureGroups.put(check.getText(),
\r
145 new Boolean(check.isSelected()));
\r
146 af.alignPanel.seqPanel.seqCanvas.repaint();
\r
147 if (af.alignPanel.overviewPanel != null)
\r
148 af.alignPanel.overviewPanel.updateOverviewImage();
\r
153 groupPanel.add(check);
\r
159 if (!allFeatures.contains(tmpfeatures[index].getType()))
\r
161 allFeatures.addElement(tmpfeatures[index].getType());
\r
168 if(!alignmentHasFeatures)
\r
171 // { frame.setClosed(true); }
\r
172 // catch (Exception ex){}
\r
174 // JOptionPane.showInternalMessageDialog(
\r
175 /// Desktop.desktop, "No features have been added to this alignment!",
\r
184 void resetTable(boolean groupsChanged)
\r
186 SequenceFeature [] tmpfeatures;
\r
187 String group=null, type;
\r
188 Vector visibleChecks = new Vector();
\r
190 //Find out which features should be visible depending on which groups
\r
191 //are selected / deselected
\r
192 for (int i = 0; i < af.getViewport().alignment.getHeight(); i++)
\r
195 tmpfeatures = af.getViewport().alignment.getSequenceAt(i).getDatasetSequence().getSequenceFeatures();
\r
196 if (tmpfeatures == null)
\r
200 while (index < tmpfeatures.length)
\r
202 group = tmpfeatures[index].featureGroup;
\r
204 if(tmpfeatures[index].begin==0 && tmpfeatures[index].end==0)
\r
210 if (group==null || fr.featureGroups.get(group)==null ||
\r
211 ((Boolean) fr.featureGroups.get(group)).booleanValue())
\r
213 type = tmpfeatures[index].getType();
\r
214 if(!visibleChecks.contains(type) )
\r
216 visibleChecks.addElement(type);
\r
223 int fSize = visibleChecks.size();
\r
224 Object [][] data = new Object[fSize][3];
\r
227 if(fr.renderOrder!=null)
\r
229 //First add the checks in the previous render order,
\r
230 //in case the window has been closed and reopened
\r
231 for(int ro=fr.renderOrder.length-1; ro>-1; ro--)
\r
233 type = fr.renderOrder[ro];
\r
235 if(!visibleChecks.contains(type))
\r
238 data[dataIndex][0] = type;
\r
239 data[dataIndex][1] = fr.getColour(type);
\r
240 data[dataIndex][2] = new Boolean(af.getViewport().featuresDisplayed.containsKey(type));
\r
242 visibleChecks.removeElement(type);
\r
246 fSize = visibleChecks.size();
\r
247 for(int i=0; i<fSize; i++)
\r
249 //These must be extra features belonging to the group
\r
250 //which was just selected
\r
251 type = visibleChecks.elementAt(i).toString();
\r
252 data[dataIndex][0] = type;
\r
254 data[dataIndex][1] = fr.getColour(type);
\r
255 data[dataIndex][2] = new Boolean(true);
\r
259 if(originalData==null)
\r
261 originalData = new Object[data.length][3];
\r
262 System.arraycopy(data,0,originalData,0,data.length);
\r
265 table = new JTable(new FeatureTableModel(data));
\r
266 scrollPane.setViewportView(table);
\r
267 table.getTableHeader().setFont(new Font("Verdana", Font.PLAIN, 12));
\r
268 table.setFont(new Font("Verdana", Font.PLAIN, 12));
\r
269 table.setDefaultRenderer(Color.class,
\r
270 new ColorRenderer());
\r
272 table.setDefaultEditor(Color.class,
\r
273 new ColorEditor());
\r
275 table.getColumnModel().getColumn(0).setPreferredWidth(200);
\r
277 table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
\r
279 table.addMouseListener(new MouseAdapter()
\r
281 public void mousePressed(MouseEvent evt)
\r
283 selectedRow = table.rowAtPoint(evt.getPoint());
\r
287 table.addMouseMotionListener(new MouseMotionAdapter()
\r
289 public void mouseDragged(MouseEvent evt)
\r
291 int newRow = table.rowAtPoint(evt.getPoint());
\r
292 if(newRow!=selectedRow
\r
296 Object[] temp = new Object[3];
\r
297 temp[0] = table.getValueAt(selectedRow, 0);
\r
298 temp[1] = table.getValueAt(selectedRow, 1);
\r
299 temp[2] = table.getValueAt(selectedRow, 2);
\r
301 table.setValueAt(table.getValueAt(newRow, 0), selectedRow, 0);
\r
302 table.setValueAt(table.getValueAt(newRow, 1), selectedRow, 1);
\r
303 table.setValueAt(table.getValueAt(newRow, 2), selectedRow, 2);
\r
305 table.setValueAt(temp[0], newRow, 0);
\r
306 table.setValueAt(temp[1], newRow, 1);
\r
307 table.setValueAt(temp[2], newRow, 2);
\r
309 selectedRow = newRow;
\r
314 if (groupPanel != null)
\r
316 groupPanel.setLayout(
\r
317 new GridLayout(fr.featureGroups.size() / 4 + 1, 4));
\r
319 groupPanel.validate();
\r
320 bigPanel.add(groupPanel, BorderLayout.NORTH);
\r
323 updateFeatureRenderer(data);
\r
329 JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.getProperty(
\r
330 "LAST_DIRECTORY"), new String[] { "fc" },
\r
331 new String[] { "Sequence Feature Colours" }, "Sequence Feature Colours");
\r
332 chooser.setFileView(new jalview.io.JalviewFileView());
\r
333 chooser.setDialogTitle("Load Feature Colours");
\r
334 chooser.setToolTipText("Load");
\r
336 int value = chooser.showOpenDialog(this);
\r
338 if (value == JalviewFileChooser.APPROVE_OPTION)
\r
340 File file = chooser.getSelectedFile();
\r
344 InputStreamReader in = new InputStreamReader(new FileInputStream(
\r
347 jalview.binding.JalviewUserColours jucs = new jalview.binding.
\r
348 JalviewUserColours();
\r
349 jucs = (jalview.binding.JalviewUserColours) jucs.unmarshal(in);
\r
352 for (int i = 0; i < jucs.getColourCount(); i++)
\r
354 fr.setColour( jucs.getColour(i).getName(),
\r
355 new Color(Integer.parseInt( jucs.getColour(i).getRGB(), 16)));
\r
359 af.alignPanel.repaint();
\r
361 catch (Exception ex)
\r
363 System.out.println("Error loading User Colour File\n" + ex);
\r
370 JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.getProperty(
\r
371 "LAST_DIRECTORY"), new String[] { "fc" },
\r
372 new String[] { "Sequence Feature Colours" }, "Sequence Feature Colours");
\r
373 chooser.setFileView(new jalview.io.JalviewFileView());
\r
374 chooser.setDialogTitle("Save Feature Colour Scheme");
\r
375 chooser.setToolTipText("Save");
\r
377 int value = chooser.showSaveDialog(this);
\r
379 if (value == JalviewFileChooser.APPROVE_OPTION)
\r
381 String choice = chooser.getSelectedFile().getPath();
\r
382 jalview.binding.JalviewUserColours ucs = new jalview.binding.JalviewUserColours();
\r
383 ucs.setSchemeName("Sequence Features");
\r
386 PrintWriter out = new PrintWriter(new OutputStreamWriter(
\r
387 new FileOutputStream(choice), "UTF-8"));
\r
389 Enumeration e = fr.featureColours.keys();
\r
390 while(e.hasMoreElements())
\r
392 jalview.binding.Colour col = new jalview.binding.Colour();
\r
393 col.setName(e.nextElement().toString());
\r
394 col.setRGB(jalview.util.Format.getHexString(
\r
395 fr.getColour(col.getName())));
\r
396 ucs.addColour(col);
\r
402 catch (Exception ex)
\r
404 ex.printStackTrace();
\r
409 public void invertSelection()
\r
411 for(int i=0; i<table.getRowCount(); i++)
\r
413 Boolean value = (Boolean)table.getValueAt(i,2);
\r
416 new Boolean(!value.booleanValue()),
\r
421 public void close()
\r
425 frame.setClosed(true);
\r
427 catch (Exception exe)
\r
432 public void updateFeatureRenderer(Object [][] data)
\r
434 fr.setFeaturePriority( data );
\r
435 af.alignPanel.repaint();
\r
437 if(af.alignPanel.overviewPanel!=null)
\r
438 af.alignPanel.overviewPanel.updateOverviewImage();
\r
441 int selectedRow =-1;
\r
442 JTabbedPane tabbedPane = new JTabbedPane();
\r
443 BorderLayout borderLayout1 = new BorderLayout();
\r
444 BorderLayout borderLayout2 = new BorderLayout();
\r
445 BorderLayout borderLayout3 = new BorderLayout();
\r
446 JPanel bigPanel = new JPanel();
\r
447 BorderLayout borderLayout4 = new BorderLayout();
\r
448 JButton invert = new JButton();
\r
449 JPanel buttonPanel = new JPanel();
\r
450 JButton cancel = new JButton();
\r
451 JButton ok = new JButton();
\r
452 JButton loadColours = new JButton();
\r
453 JButton saveColours = new JButton();
\r
454 JPanel dasButtonPanel = new JPanel();
\r
455 JButton fetchDAS = new JButton();
\r
456 JButton saveDAS = new JButton();
\r
457 private void jbInit()
\r
460 this.setLayout(borderLayout1);
\r
461 settingsPane.setLayout(borderLayout2);
\r
462 dasSettingsPane.setLayout(borderLayout3);
\r
463 bigPanel.setLayout(borderLayout4);
\r
464 invert.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
\r
465 invert.setText("Invert Selection");
\r
466 invert.addActionListener(new ActionListener()
\r
468 public void actionPerformed(ActionEvent e)
\r
473 cancel.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
\r
474 cancel.setText("Cancel");
\r
475 cancel.addActionListener(new ActionListener()
\r
477 public void actionPerformed(ActionEvent e)
\r
479 updateFeatureRenderer(originalData);
\r
483 ok.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
\r
485 ok.addActionListener(new ActionListener()
\r
487 public void actionPerformed(ActionEvent e)
\r
492 loadColours.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
\r
493 loadColours.setText("Load Colours");
\r
494 loadColours.addActionListener(new ActionListener()
\r
496 public void actionPerformed(ActionEvent e)
\r
501 saveColours.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
\r
502 saveColours.setText("Save Colours");
\r
503 saveColours.addActionListener(new ActionListener()
\r
505 public void actionPerformed(ActionEvent e)
\r
510 transparency.addChangeListener(new ChangeListener()
\r
512 public void stateChanged(ChangeEvent evt)
\r
514 fr.setTransparency( (float) (100 - transparency.getValue()) / 100f);
\r
515 af.alignPanel.repaint();
\r
520 transparency.setMaximum(70);
\r
521 fetchDAS.setText("Fetch DAS Features");
\r
522 fetchDAS.addActionListener(new ActionListener()
\r
524 public void actionPerformed(ActionEvent e)
\r
526 fetchDAS_actionPerformed(e);
\r
529 saveDAS.setText("Save as default");
\r
530 saveDAS.addActionListener(new ActionListener()
\r
532 public void actionPerformed(ActionEvent e)
\r
534 saveDAS_actionPerformed(e);
\r
537 dasButtonPanel.setBorder(BorderFactory.createEtchedBorder());
\r
538 dasSettingsPane.setBorder(null);
\r
539 this.add(tabbedPane, java.awt.BorderLayout.CENTER);
\r
540 tabbedPane.addTab("Display Settings", settingsPane );
\r
541 tabbedPane.addTab("DAS Settings", dasSettingsPane);
\r
542 bigPanel.add(transPanel, java.awt.BorderLayout.SOUTH);
\r
543 transPanel.add(transparency);
\r
544 transPanel.add(invert);
\r
545 buttonPanel.add(ok);
\r
546 buttonPanel.add(cancel);
\r
547 buttonPanel.add(loadColours);
\r
548 buttonPanel.add(saveColours);
\r
549 bigPanel.add(scrollPane, java.awt.BorderLayout.CENTER);
\r
550 dasSettingsPane.add(dasButtonPanel, java.awt.BorderLayout.SOUTH);
\r
551 dasButtonPanel.add(fetchDAS);
\r
552 dasButtonPanel.add(saveDAS);
\r
553 settingsPane.add(bigPanel, java.awt.BorderLayout.CENTER);
\r
554 settingsPane.add(buttonPanel, java.awt.BorderLayout.SOUTH);
\r
557 public void fetchDAS_actionPerformed(ActionEvent e)
\r
559 Vector selectedSources = dassourceBrowser.getSelectedSources();
\r
561 SequenceI [] dataset, seqs ;
\r
564 if(af.getViewport().getSelectionGroup()!=null
\r
565 && af.getViewport().getSelectionGroup().getSize(false)>0)
\r
567 iSize = af.getViewport().getSelectionGroup().getSize(false);
\r
568 dataset = new SequenceI[iSize];
\r
569 seqs = af.getViewport().getSelectionGroup().
\r
570 getSequencesInOrder(
\r
571 af.getViewport().getAlignment());
\r
575 iSize = af.getViewport().getAlignment().getHeight();
\r
576 seqs = af.getViewport().getAlignment().getSequencesArray();
\r
579 dataset = new SequenceI[iSize];
\r
580 for (int i = 0; i < iSize; i++)
\r
582 dataset[i] = seqs[i].getDatasetSequence();
\r
585 new jalview.io.DasSequenceFeatureFetcher(
\r
590 af.getViewport().setShowSequenceFeatures(true);
\r
591 af.showSeqFeatures.setSelected(true);
\r
594 public void saveDAS_actionPerformed(ActionEvent e)
\r
596 dassourceBrowser.saveProperties(jalview.bin.Cache.applicationProperties);
\r
599 /////////////////////////////////////////////////////////////////////////
\r
600 // http://java.sun.com/docs/books/tutorial/uiswing/components/table.html
\r
601 /////////////////////////////////////////////////////////////////////////
\r
602 class FeatureTableModel
\r
603 extends AbstractTableModel
\r
605 FeatureTableModel(Object[][] data)
\r
610 private String[] columnNames = {"Feature Type", "Colour","Display"};
\r
611 private Object[][] data;
\r
613 public Object[][] getData()
\r
618 public void setData(Object[][] data)
\r
623 public int getColumnCount() {
\r
624 return columnNames.length;
\r
627 public Object[] getRow(int row)
\r
632 public int getRowCount() {
\r
633 return data.length;
\r
636 public String getColumnName(int col) {
\r
637 return columnNames[col];
\r
640 public Object getValueAt(int row, int col) {
\r
641 return data[row][col];
\r
644 public Class getColumnClass(int c) {
\r
645 return getValueAt(0, c).getClass();
\r
648 public boolean isCellEditable(int row, int col) {
\r
649 return col==0 ? false:true;
\r
652 public void setValueAt(Object value, int row, int col) {
\r
653 data[row][col] = value;
\r
654 fireTableCellUpdated(row, col);
\r
655 updateFeatureRenderer(data);
\r
659 class ColorRenderer extends JLabel
\r
660 implements TableCellRenderer {
\r
661 javax.swing.border.Border unselectedBorder = null;
\r
662 javax.swing.border.Border selectedBorder = null;
\r
664 public ColorRenderer() {
\r
665 setOpaque(true); //MUST do this for background to show up.
\r
668 public Component getTableCellRendererComponent(
\r
669 JTable table, Object color,
\r
670 boolean isSelected, boolean hasFocus,
\r
671 int row, int column) {
\r
672 Color newColor = (Color)color;
\r
673 setBackground(newColor);
\r
675 if (selectedBorder == null) {
\r
676 selectedBorder = BorderFactory.createMatteBorder(2,5,2,5,
\r
677 table.getSelectionBackground());
\r
679 setBorder(selectedBorder);
\r
681 if (unselectedBorder == null) {
\r
682 unselectedBorder = BorderFactory.createMatteBorder(2,5,2,5,
\r
683 table.getBackground());
\r
685 setBorder(unselectedBorder);
\r
688 setToolTipText("RGB value: " + newColor.getRed() + ", "
\r
689 + newColor.getGreen() + ", "
\r
690 + newColor.getBlue());
\r
696 class ColorEditor extends AbstractCellEditor
\r
697 implements TableCellEditor,
\r
699 Color currentColor;
\r
701 JColorChooser colorChooser;
\r
703 protected static final String EDIT = "edit";
\r
705 public ColorEditor() {
\r
706 //Set up the editor (from the table's point of view),
\r
707 //which is a button.
\r
708 //This button brings up the color chooser dialog,
\r
709 //which is the editor from the user's point of view.
\r
710 button = new JButton();
\r
711 button.setActionCommand(EDIT);
\r
712 button.addActionListener(this);
\r
713 button.setBorderPainted(false);
\r
714 //Set up the dialog that the button brings up.
\r
715 colorChooser = new JColorChooser();
\r
716 dialog = JColorChooser.createDialog(button,
\r
717 "Select new Colour",
\r
720 this, //OK button handler
\r
721 null); //no CANCEL button handler
\r
725 * Handles events from the editor button and from
\r
726 * the dialog's OK button.
\r
728 public void actionPerformed(ActionEvent e) {
\r
730 if (EDIT.equals(e.getActionCommand())) {
\r
731 //The user has clicked the cell, so
\r
732 //bring up the dialog.
\r
733 button.setBackground(currentColor);
\r
734 colorChooser.setColor(currentColor);
\r
735 dialog.setVisible(true);
\r
737 //Make the renderer reappear.
\r
738 fireEditingStopped();
\r
740 } else { //User pressed dialog's "OK" button.
\r
741 currentColor = colorChooser.getColor();
\r
745 //Implement the one CellEditor method that AbstractCellEditor doesn't.
\r
746 public Object getCellEditorValue() {
\r
747 return currentColor;
\r
750 //Implement the one method defined by TableCellEditor.
\r
751 public Component getTableCellEditorComponent(JTable table,
\r
753 boolean isSelected,
\r
756 currentColor = (Color)value;
\r