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
80 frame = new JInternalFrame();
\r
81 frame.setContentPane(this);
\r
82 Desktop.addInternalFrame(frame, "Sequence Feature Settings", 400, 450);
\r
83 frame.setLayer(JLayeredPane.PALETTE_LAYER);
\r
86 public void setTableData()
\r
88 alignmentHasFeatures = false;
\r
90 if (fr.featureGroups == null)
\r
91 fr.featureGroups = new Hashtable();
\r
93 Vector allFeatures = new Vector();
\r
94 Vector allGroups = new Vector();
\r
95 SequenceFeature[] tmpfeatures;
\r
98 for (int i = 0; i < af.getViewport().alignment.getHeight(); i++)
\r
100 if (af.getViewport().alignment.getSequenceAt(i).getDatasetSequence().getSequenceFeatures() == null)
\r
103 alignmentHasFeatures = true;
\r
105 tmpfeatures = af.getViewport().alignment.getSequenceAt(i).getDatasetSequence().getSequenceFeatures();
\r
108 while (index < tmpfeatures.length)
\r
110 if(tmpfeatures[index].begin == 0 && tmpfeatures[index].end ==0)
\r
116 if(tmpfeatures[index].getFeatureGroup()!=null)
\r
118 group = tmpfeatures[index].featureGroup;
\r
119 if(!allGroups.contains(group))
\r
121 allGroups.addElement(group);
\r
123 boolean visible = true;
\r
124 if (fr.featureGroups.containsKey(group))
\r
126 visible = ( (Boolean) fr.featureGroups.get(group)).booleanValue();
\r
130 fr.featureGroups.put(group, new Boolean(visible));
\r
131 if (groupPanel == null)
\r
133 groupPanel = new JPanel();
\r
136 final JCheckBox check = new JCheckBox(group, visible);
\r
137 check.setFont(new Font("Serif", Font.BOLD, 12));
\r
138 check.addItemListener(new ItemListener()
\r
140 public void itemStateChanged(ItemEvent evt)
\r
142 fr.featureGroups.put(check.getText(),
\r
143 new Boolean(check.isSelected()));
\r
144 af.alignPanel.seqPanel.seqCanvas.repaint();
\r
145 if (af.alignPanel.overviewPanel != null)
\r
146 af.alignPanel.overviewPanel.updateOverviewImage();
\r
151 groupPanel.add(check);
\r
157 if (!allFeatures.contains(tmpfeatures[index].getType()))
\r
159 allFeatures.addElement(tmpfeatures[index].getType());
\r
166 if(!alignmentHasFeatures)
\r
169 // { frame.setClosed(true); }
\r
170 // catch (Exception ex){}
\r
172 // JOptionPane.showInternalMessageDialog(
\r
173 /// Desktop.desktop, "No features have been added to this alignment!",
\r
182 void resetTable(boolean groupsChanged)
\r
184 SequenceFeature [] tmpfeatures;
\r
185 String group=null, type;
\r
186 Vector visibleChecks = new Vector();
\r
188 //Find out which features should be visible depending on which groups
\r
189 //are selected / deselected
\r
190 for (int i = 0; i < af.getViewport().alignment.getHeight(); i++)
\r
193 tmpfeatures = af.getViewport().alignment.getSequenceAt(i).getDatasetSequence().getSequenceFeatures();
\r
194 if (tmpfeatures == null)
\r
198 while (index < tmpfeatures.length)
\r
200 group = tmpfeatures[index].featureGroup;
\r
202 if(tmpfeatures[index].begin==0 && tmpfeatures[index].end==0)
\r
208 if (group==null || fr.featureGroups.get(group)==null ||
\r
209 ((Boolean) fr.featureGroups.get(group)).booleanValue())
\r
211 type = tmpfeatures[index].getType();
\r
212 if(!visibleChecks.contains(type) )
\r
214 visibleChecks.addElement(type);
\r
221 int fSize = visibleChecks.size();
\r
222 Object [][] data = new Object[fSize][3];
\r
225 if(fr.renderOrder!=null)
\r
227 //First add the checks in the previous render order,
\r
228 //in case the window has been closed and reopened
\r
229 for(int ro=fr.renderOrder.length-1; ro>-1; ro--)
\r
231 type = fr.renderOrder[ro];
\r
233 if(!visibleChecks.contains(type))
\r
236 data[dataIndex][0] = type;
\r
237 data[dataIndex][1] = fr.getColour(type);
\r
238 data[dataIndex][2] = new Boolean(af.getViewport().featuresDisplayed.containsKey(type));
\r
240 visibleChecks.removeElement(type);
\r
244 fSize = visibleChecks.size();
\r
245 for(int i=0; i<fSize; i++)
\r
247 //These must be extra features belonging to the group
\r
248 //which was just selected
\r
249 type = visibleChecks.elementAt(i).toString();
\r
250 data[dataIndex][0] = type;
\r
252 data[dataIndex][1] = fr.getColour(type);
\r
253 data[dataIndex][2] = new Boolean(true);
\r
257 if(originalData==null)
\r
259 originalData = new Object[data.length][3];
\r
260 System.arraycopy(data,0,originalData,0,data.length);
\r
263 table = new JTable(new FeatureTableModel(data));
\r
264 scrollPane.setViewportView(table);
\r
265 table.getTableHeader().setFont(new Font("Verdana", Font.PLAIN, 12));
\r
266 table.setFont(new Font("Verdana", Font.PLAIN, 12));
\r
267 table.setDefaultRenderer(Color.class,
\r
268 new ColorRenderer());
\r
270 table.setDefaultEditor(Color.class,
\r
271 new ColorEditor());
\r
273 table.getColumnModel().getColumn(0).setPreferredWidth(200);
\r
275 table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
\r
277 table.addMouseListener(new MouseAdapter()
\r
279 public void mousePressed(MouseEvent evt)
\r
281 selectedRow = table.rowAtPoint(evt.getPoint());
\r
285 table.addMouseMotionListener(new MouseMotionAdapter()
\r
287 public void mouseDragged(MouseEvent evt)
\r
289 int newRow = table.rowAtPoint(evt.getPoint());
\r
290 if(newRow!=selectedRow
\r
294 Object[] temp = new Object[3];
\r
295 temp[0] = table.getValueAt(selectedRow, 0);
\r
296 temp[1] = table.getValueAt(selectedRow, 1);
\r
297 temp[2] = table.getValueAt(selectedRow, 2);
\r
299 table.setValueAt(table.getValueAt(newRow, 0), selectedRow, 0);
\r
300 table.setValueAt(table.getValueAt(newRow, 1), selectedRow, 1);
\r
301 table.setValueAt(table.getValueAt(newRow, 2), selectedRow, 2);
\r
303 table.setValueAt(temp[0], newRow, 0);
\r
304 table.setValueAt(temp[1], newRow, 1);
\r
305 table.setValueAt(temp[2], newRow, 2);
\r
307 selectedRow = newRow;
\r
312 if (groupPanel != null)
\r
314 groupPanel.setLayout(
\r
315 new GridLayout(fr.featureGroups.size() / 4 + 1, 4));
\r
317 groupPanel.validate();
\r
318 bigPanel.add(groupPanel, BorderLayout.NORTH);
\r
321 updateFeatureRenderer(data);
\r
327 JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.getProperty(
\r
328 "LAST_DIRECTORY"), new String[] { "fc" },
\r
329 new String[] { "Sequence Feature Colours" }, "Sequence Feature Colours");
\r
330 chooser.setFileView(new jalview.io.JalviewFileView());
\r
331 chooser.setDialogTitle("Load Feature Colours");
\r
332 chooser.setToolTipText("Load");
\r
334 int value = chooser.showOpenDialog(this);
\r
336 if (value == JalviewFileChooser.APPROVE_OPTION)
\r
338 File file = chooser.getSelectedFile();
\r
342 InputStreamReader in = new InputStreamReader(new FileInputStream(
\r
345 jalview.binding.JalviewUserColours jucs = new jalview.binding.
\r
346 JalviewUserColours();
\r
347 jucs = (jalview.binding.JalviewUserColours) jucs.unmarshal(in);
\r
350 for (int i = 0; i < jucs.getColourCount(); i++)
\r
352 fr.setColour( jucs.getColour(i).getName(),
\r
353 new Color(Integer.parseInt( jucs.getColour(i).getRGB(), 16)));
\r
357 af.alignPanel.repaint();
\r
359 catch (Exception ex)
\r
361 System.out.println("Error loading User Colour File\n" + ex);
\r
368 JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.getProperty(
\r
369 "LAST_DIRECTORY"), new String[] { "fc" },
\r
370 new String[] { "Sequence Feature Colours" }, "Sequence Feature Colours");
\r
371 chooser.setFileView(new jalview.io.JalviewFileView());
\r
372 chooser.setDialogTitle("Save Feature Colour Scheme");
\r
373 chooser.setToolTipText("Save");
\r
375 int value = chooser.showSaveDialog(this);
\r
377 if (value == JalviewFileChooser.APPROVE_OPTION)
\r
379 String choice = chooser.getSelectedFile().getPath();
\r
380 jalview.binding.JalviewUserColours ucs = new jalview.binding.JalviewUserColours();
\r
381 ucs.setSchemeName("Sequence Features");
\r
384 PrintWriter out = new PrintWriter(new OutputStreamWriter(
\r
385 new FileOutputStream(choice), "UTF-8"));
\r
387 Enumeration e = fr.featureColours.keys();
\r
388 while(e.hasMoreElements())
\r
390 jalview.binding.Colour col = new jalview.binding.Colour();
\r
391 col.setName(e.nextElement().toString());
\r
392 col.setRGB(jalview.util.Format.getHexString(
\r
393 fr.getColour(col.getName())));
\r
394 ucs.addColour(col);
\r
400 catch (Exception ex)
\r
402 ex.printStackTrace();
\r
407 public void invertSelection()
\r
409 for(int i=0; i<table.getRowCount(); i++)
\r
411 Boolean value = (Boolean)table.getValueAt(i,2);
\r
414 new Boolean(!value.booleanValue()),
\r
419 public void close()
\r
423 frame.setClosed(true);
\r
425 catch (Exception exe)
\r
430 public void updateFeatureRenderer(Object [][] data)
\r
432 fr.setFeaturePriority( data );
\r
433 af.alignPanel.repaint();
\r
435 if(af.alignPanel.overviewPanel!=null)
\r
436 af.alignPanel.overviewPanel.updateOverviewImage();
\r
439 int selectedRow =-1;
\r
440 JTabbedPane tabbedPane = new JTabbedPane();
\r
441 BorderLayout borderLayout1 = new BorderLayout();
\r
442 BorderLayout borderLayout2 = new BorderLayout();
\r
443 BorderLayout borderLayout3 = new BorderLayout();
\r
444 JPanel bigPanel = new JPanel();
\r
445 BorderLayout borderLayout4 = new BorderLayout();
\r
446 JButton invert = new JButton();
\r
447 JPanel buttonPanel = new JPanel();
\r
448 JButton cancel = new JButton();
\r
449 JButton ok = new JButton();
\r
450 JButton loadColours = new JButton();
\r
451 JButton saveColours = new JButton();
\r
452 JPanel dasButtonPanel = new JPanel();
\r
453 JButton fetchDAS = new JButton();
\r
454 JButton saveDAS = new JButton();
\r
455 private void jbInit()
\r
458 this.setLayout(borderLayout1);
\r
459 settingsPane.setLayout(borderLayout2);
\r
460 dasSettingsPane.setLayout(borderLayout3);
\r
461 bigPanel.setLayout(borderLayout4);
\r
462 invert.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
\r
463 invert.setText("Invert Selection");
\r
464 invert.addActionListener(new ActionListener()
\r
466 public void actionPerformed(ActionEvent e)
\r
471 cancel.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
\r
472 cancel.setText("Cancel");
\r
473 cancel.addActionListener(new ActionListener()
\r
475 public void actionPerformed(ActionEvent e)
\r
477 updateFeatureRenderer(originalData);
\r
481 ok.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
\r
483 ok.addActionListener(new ActionListener()
\r
485 public void actionPerformed(ActionEvent e)
\r
490 loadColours.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
\r
491 loadColours.setText("Load Colours");
\r
492 loadColours.addActionListener(new ActionListener()
\r
494 public void actionPerformed(ActionEvent e)
\r
499 saveColours.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
\r
500 saveColours.setText("Save Colours");
\r
501 saveColours.addActionListener(new ActionListener()
\r
503 public void actionPerformed(ActionEvent e)
\r
508 transparency.addChangeListener(new ChangeListener()
\r
510 public void stateChanged(ChangeEvent evt)
\r
512 fr.setTransparency( (float) (100 - transparency.getValue()) / 100f);
\r
513 af.alignPanel.repaint();
\r
518 transparency.setMaximum(70);
\r
519 fetchDAS.setText("Fetch DAS Features");
\r
520 fetchDAS.addActionListener(new ActionListener()
\r
522 public void actionPerformed(ActionEvent e)
\r
524 fetchDAS_actionPerformed(e);
\r
527 saveDAS.setText("Save as default");
\r
528 saveDAS.addActionListener(new ActionListener()
\r
530 public void actionPerformed(ActionEvent e)
\r
532 saveDAS_actionPerformed(e);
\r
535 dasButtonPanel.setBorder(BorderFactory.createEtchedBorder());
\r
536 dasSettingsPane.setBorder(null);
\r
537 this.add(tabbedPane, java.awt.BorderLayout.CENTER);
\r
538 tabbedPane.addTab("Display Settings", settingsPane );
\r
539 tabbedPane.addTab("DAS Settings", dasSettingsPane);
\r
540 bigPanel.add(transPanel, java.awt.BorderLayout.SOUTH);
\r
541 transPanel.add(transparency);
\r
542 transPanel.add(invert);
\r
543 buttonPanel.add(ok);
\r
544 buttonPanel.add(cancel);
\r
545 buttonPanel.add(loadColours);
\r
546 buttonPanel.add(saveColours);
\r
547 bigPanel.add(scrollPane, java.awt.BorderLayout.CENTER);
\r
548 dasSettingsPane.add(dasButtonPanel, java.awt.BorderLayout.SOUTH);
\r
549 dasButtonPanel.add(fetchDAS);
\r
550 dasButtonPanel.add(saveDAS);
\r
551 settingsPane.add(bigPanel, java.awt.BorderLayout.CENTER);
\r
552 settingsPane.add(buttonPanel, java.awt.BorderLayout.SOUTH);
\r
555 public void fetchDAS_actionPerformed(ActionEvent e)
\r
557 Vector selectedSources = dassourceBrowser.getSelectedSources();
\r
559 SequenceI [] dataset, seqs ;
\r
562 if(af.getViewport().getSelectionGroup()!=null
\r
563 && af.getViewport().getSelectionGroup().getSize(false)>0)
\r
565 iSize = af.getViewport().getSelectionGroup().getSize(false);
\r
566 dataset = new SequenceI[iSize];
\r
567 seqs = af.getViewport().getSelectionGroup().
\r
568 getSequencesInOrder(
\r
569 af.getViewport().getAlignment());
\r
573 iSize = af.getViewport().getAlignment().getHeight();
\r
574 seqs = af.getViewport().getAlignment().getSequencesArray();
\r
577 dataset = new SequenceI[iSize];
\r
578 for (int i = 0; i < iSize; i++)
\r
580 dataset[i] = seqs[i].getDatasetSequence();
\r
583 new jalview.io.DasSequenceFeatureFetcher(
\r
588 af.getViewport().setShowSequenceFeatures(true);
\r
589 af.showSeqFeatures.setSelected(true);
\r
592 public void saveDAS_actionPerformed(ActionEvent e)
\r
594 dassourceBrowser.saveProperties(jalview.bin.Cache.applicationProperties);
\r
597 /////////////////////////////////////////////////////////////////////////
\r
598 // http://java.sun.com/docs/books/tutorial/uiswing/components/table.html
\r
599 /////////////////////////////////////////////////////////////////////////
\r
600 class FeatureTableModel
\r
601 extends AbstractTableModel
\r
603 FeatureTableModel(Object[][] data)
\r
608 private String[] columnNames = {"Feature Type", "Colour","Display"};
\r
609 private Object[][] data;
\r
611 public Object[][] getData()
\r
616 public void setData(Object[][] data)
\r
621 public int getColumnCount() {
\r
622 return columnNames.length;
\r
625 public Object[] getRow(int row)
\r
630 public int getRowCount() {
\r
631 return data.length;
\r
634 public String getColumnName(int col) {
\r
635 return columnNames[col];
\r
638 public Object getValueAt(int row, int col) {
\r
639 return data[row][col];
\r
642 public Class getColumnClass(int c) {
\r
643 return getValueAt(0, c).getClass();
\r
646 public boolean isCellEditable(int row, int col) {
\r
647 return col==0 ? false:true;
\r
650 public void setValueAt(Object value, int row, int col) {
\r
651 data[row][col] = value;
\r
652 fireTableCellUpdated(row, col);
\r
653 updateFeatureRenderer(data);
\r
657 class ColorRenderer extends JLabel
\r
658 implements TableCellRenderer {
\r
659 javax.swing.border.Border unselectedBorder = null;
\r
660 javax.swing.border.Border selectedBorder = null;
\r
662 public ColorRenderer() {
\r
663 setOpaque(true); //MUST do this for background to show up.
\r
666 public Component getTableCellRendererComponent(
\r
667 JTable table, Object color,
\r
668 boolean isSelected, boolean hasFocus,
\r
669 int row, int column) {
\r
670 Color newColor = (Color)color;
\r
671 setBackground(newColor);
\r
673 if (selectedBorder == null) {
\r
674 selectedBorder = BorderFactory.createMatteBorder(2,5,2,5,
\r
675 table.getSelectionBackground());
\r
677 setBorder(selectedBorder);
\r
679 if (unselectedBorder == null) {
\r
680 unselectedBorder = BorderFactory.createMatteBorder(2,5,2,5,
\r
681 table.getBackground());
\r
683 setBorder(unselectedBorder);
\r
686 setToolTipText("RGB value: " + newColor.getRed() + ", "
\r
687 + newColor.getGreen() + ", "
\r
688 + newColor.getBlue());
\r
694 class ColorEditor extends AbstractCellEditor
\r
695 implements TableCellEditor,
\r
697 Color currentColor;
\r
699 JColorChooser colorChooser;
\r
701 protected static final String EDIT = "edit";
\r
703 public ColorEditor() {
\r
704 //Set up the editor (from the table's point of view),
\r
705 //which is a button.
\r
706 //This button brings up the color chooser dialog,
\r
707 //which is the editor from the user's point of view.
\r
708 button = new JButton();
\r
709 button.setActionCommand(EDIT);
\r
710 button.addActionListener(this);
\r
711 button.setBorderPainted(false);
\r
712 //Set up the dialog that the button brings up.
\r
713 colorChooser = new JColorChooser();
\r
714 dialog = JColorChooser.createDialog(button,
\r
715 "Select new Colour",
\r
718 this, //OK button handler
\r
719 null); //no CANCEL button handler
\r
723 * Handles events from the editor button and from
\r
724 * the dialog's OK button.
\r
726 public void actionPerformed(ActionEvent e) {
\r
728 if (EDIT.equals(e.getActionCommand())) {
\r
729 //The user has clicked the cell, so
\r
730 //bring up the dialog.
\r
731 button.setBackground(currentColor);
\r
732 colorChooser.setColor(currentColor);
\r
733 dialog.setVisible(true);
\r
735 //Make the renderer reappear.
\r
736 fireEditingStopped();
\r
738 } else { //User pressed dialog's "OK" button.
\r
739 currentColor = colorChooser.getColor();
\r
743 //Implement the one CellEditor method that AbstractCellEditor doesn't.
\r
744 public Object getCellEditorValue() {
\r
745 return currentColor;
\r
748 //Implement the one method defined by TableCellEditor.
\r
749 public Component getTableCellEditorComponent(JTable table,
\r
751 boolean isSelected,
\r
754 currentColor = (Color)value;
\r