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
32 public class FeatureSettings extends JPanel
\r
35 final FeatureRenderer fr;
\r
36 final AlignmentPanel ap;
\r
37 final AlignViewport av;
\r
38 Hashtable allFeatures;
\r
39 Object [][] originalData;
\r
40 final JInternalFrame frame;
\r
41 JScrollPane scrollPane = new JScrollPane();
\r
45 public FeatureSettings(AlignViewport av, final AlignmentPanel ap)
\r
49 fr = ap.seqPanel.seqCanvas.getFeatureRenderer();
\r
50 av.alignment.getSequences();
\r
51 frame = new JInternalFrame();
\r
52 frame.setContentPane(this);
\r
53 Desktop.addInternalFrame(frame, "Sequence Feature Settings", 400, 300);
\r
57 final JSlider transparency = new JSlider(0, 70, 0);
\r
58 transparency.addChangeListener(new ChangeListener()
\r
60 public void stateChanged(ChangeEvent evt)
\r
62 fr.setTransparency( (float) (100 - transparency.getValue()) / 100f);
\r
67 JPanel transPanel = new JPanel(new FlowLayout());
\r
68 transPanel.add(new JLabel("Transparency"));
\r
69 transPanel.add(transparency);
\r
71 //////////////////////////////////////////////
\r
72 //We're going to need those OK cancel buttons
\r
73 JPanel buttonPanel = new JPanel(new FlowLayout());
\r
74 JButton button = new JButton("OK");
\r
75 button.addActionListener(new ActionListener()
\r
77 public void actionPerformed(ActionEvent evt)
\r
81 frame.setClosed(true);
\r
83 catch (Exception exe)
\r
87 buttonPanel.add(button);
\r
88 button = new JButton("Cancel");
\r
89 button.addActionListener(new ActionListener()
\r
91 public void actionPerformed(ActionEvent evt)
\r
95 updateFeatureRenderer(originalData);
\r
96 frame.setClosed(true);
\r
98 catch (Exception exe)
\r
102 buttonPanel.add(button);
\r
104 button = new JButton("Load Colours");
\r
105 button.addActionListener(new ActionListener()
\r
107 public void actionPerformed(ActionEvent evt)
\r
112 buttonPanel.add(button);
\r
113 button = new JButton("Save Colours");
\r
114 button.addActionListener(new ActionListener()
\r
116 public void actionPerformed(ActionEvent evt)
\r
121 buttonPanel.add(button);
\r
123 this.setLayout(new BorderLayout());
\r
124 JPanel bigPanel = new JPanel(new BorderLayout());
\r
125 bigPanel.add(transPanel, BorderLayout.SOUTH);
\r
126 bigPanel.add(scrollPane, BorderLayout.CENTER);
\r
127 if(groupPanel!=null)
\r
129 groupPanel.setLayout(
\r
130 new GridLayout(groupPanel.getComponentCount()/3, 4));
\r
131 groupPanel.validate();
\r
132 bigPanel.add(groupPanel, BorderLayout.NORTH);
\r
134 add(bigPanel, BorderLayout.CENTER);
\r
135 add(buttonPanel, BorderLayout.SOUTH);
\r
140 void setTableData()
\r
142 if (fr.featureGroups == null)
\r
143 fr.featureGroups = new Hashtable();
\r
145 fr.featureGroups.clear();
\r
147 allFeatures = new Hashtable();
\r
148 SequenceFeature[] features;
\r
150 for (int i = 0; i < av.alignment.getHeight(); i++)
\r
152 features = av.alignment.getSequenceAt(i).getDatasetSequence().
\r
153 getSequenceFeatures();
\r
155 if (features == null)
\r
159 while (index < features.length)
\r
161 if(features[index].getFeatureGroup()!=null
\r
162 && !fr.featureGroups.containsKey(features[index].getFeatureGroup()))
\r
164 fr.featureGroups.put(features[index].getFeatureGroup(), new Boolean(true));
\r
165 if(groupPanel==null)
\r
166 groupPanel = new JPanel();
\r
168 final JCheckBox check = new JCheckBox(features[index].getFeatureGroup(), true);
\r
169 check.setFont(new Font("Serif", Font.BOLD, 12));
\r
170 check.addItemListener(new ItemListener()
\r
172 public void itemStateChanged(ItemEvent evt)
\r
174 if (fr.featureGroups.containsKey(check.getText()))
\r
176 fr.featureGroups.put(check.getText(),
\r
177 new Boolean(check.isSelected()));
\r
178 ap.seqPanel.seqCanvas.repaint();
\r
179 if (ap.overviewPanel != null)
\r
180 ap.overviewPanel.updateOverviewImage();
\r
185 groupPanel.add(check);
\r
187 if (!allFeatures.contains(features[index].getType()))
\r
189 if(features[index].featureGroup!=null)
\r
190 allFeatures.put(features[index].getType(), features[index].featureGroup);
\r
192 allFeatures.put(features[index].getType(), "NOGROUP");
\r
197 if(allFeatures.size()<1)
\r
200 { frame.setClosed(true); }
\r
201 catch (Exception ex){}
\r
203 JOptionPane.showInternalMessageDialog(
\r
204 Desktop.desktop, "No features have been added to this alignment!",
\r
205 "No Sequence Features", JOptionPane.WARNING_MESSAGE);
\r
215 int fSize = allFeatures.size();
\r
218 boolean originalExists = false;
\r
219 if (originalData != null)
\r
220 originalExists = true;
\r
222 originalData = new Object[fSize][3];
\r
224 Object[][] tmp = new Object[fSize][3];
\r
227 Enumeration en = allFeatures.keys();
\r
229 while(en.hasMoreElements())
\r
231 type = en.nextElement().toString();
\r
232 Color col = fr.getColour(type);
\r
234 //This will ignore any features which are in groups not shown
\r
235 Object visibleGroup = fr.featureGroups.get(allFeatures.get(type));
\r
236 if(visibleGroup == null
\r
237 || ((Boolean)(visibleGroup)).booleanValue())
\r
239 tmp[tmpIndex][0] = type;
\r
240 tmp[tmpIndex][1] = col;
\r
241 if (av.featuresDisplayed != null)
\r
242 tmp[tmpIndex][2] = new Boolean(av.featuresDisplayed.containsKey(type));
\r
244 tmp[tmpIndex][2] = new Boolean(true);
\r
250 if (!originalExists)
\r
252 originalData[i][0] = type;
\r
253 originalData[i][1] = col;
\r
254 if (av.featuresDisplayed != null)
\r
255 originalData[i][2] = new Boolean(av.featuresDisplayed.contains(type));
\r
257 originalData[i][2] = new Boolean(true);
\r
262 Object [][]data = new Object[tmpIndex][3];
\r
263 System.arraycopy(tmp, 0, data,0, tmpIndex);
\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 updateFeatureRenderer(data);
\r
320 JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.getProperty(
\r
321 "LAST_DIRECTORY"), new String[] { "fc" },
\r
322 new String[] { "Sequence Feature Colours" }, "Sequence Feature Colours");
\r
323 chooser.setFileView(new jalview.io.JalviewFileView());
\r
324 chooser.setDialogTitle("Load Feature Colours");
\r
325 chooser.setToolTipText("Load");
\r
327 int value = chooser.showOpenDialog(this);
\r
329 if (value == JalviewFileChooser.APPROVE_OPTION)
\r
331 File file = chooser.getSelectedFile();
\r
335 InputStreamReader in = new InputStreamReader(new FileInputStream(
\r
338 jalview.binding.JalviewUserColours jucs = new jalview.binding.
\r
339 JalviewUserColours();
\r
340 jucs = (jalview.binding.JalviewUserColours) jucs.unmarshal(in);
\r
343 for (int i = 0; i < jucs.getColourCount(); i++)
\r
345 fr.setColour( jucs.getColour(i).getName(),
\r
346 new Color(Integer.parseInt( jucs.getColour(i).getRGB(), 16)));
\r
352 catch (Exception ex)
\r
354 System.out.println("Error loading User ColourFile\n" + ex);
\r
361 JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.getProperty(
\r
362 "LAST_DIRECTORY"), new String[] { "fc" },
\r
363 new String[] { "Sequence Feature Colours" }, "Sequence Feature Colours");
\r
364 chooser.setFileView(new jalview.io.JalviewFileView());
\r
365 chooser.setDialogTitle("Save Feature Colour Scheme");
\r
366 chooser.setToolTipText("Save");
\r
368 int value = chooser.showSaveDialog(this);
\r
370 if (value == JalviewFileChooser.APPROVE_OPTION)
\r
372 String choice = chooser.getSelectedFile().getPath();
\r
373 jalview.binding.JalviewUserColours ucs = new jalview.binding.JalviewUserColours();
\r
374 ucs.setSchemeName("Sequence Features");
\r
377 PrintWriter out = new PrintWriter(new OutputStreamWriter(
\r
378 new FileOutputStream(choice), "UTF-8"));
\r
380 Enumeration e = fr.featureColours.keys();
\r
381 while(e.hasMoreElements())
\r
385 jalview.binding.Colour col = new jalview.binding.Colour();
\r
386 col.setName(e.nextElement().toString());
\r
387 col.setRGB(jalview.util.Format.getHexString(
\r
388 fr.getColour(col.getName())));
\r
389 ucs.addColour(col);
\r
395 catch (Exception ex)
\r
397 ex.printStackTrace();
\r
403 public void updateFeatureRenderer(Object [][] data)
\r
405 fr.setFeaturePriority( data );
\r
408 if(ap.overviewPanel!=null)
\r
409 ap.overviewPanel.updateOverviewImage();
\r
412 int selectedRow =-1;
\r
415 /////////////////////////////////////////////////////////////////////////
\r
416 // http://java.sun.com/docs/books/tutorial/uiswing/components/table.html
\r
417 /////////////////////////////////////////////////////////////////////////
\r
418 class FeatureTableModel
\r
419 extends AbstractTableModel
\r
421 FeatureTableModel(Object[][] data)
\r
426 private String[] columnNames = {"Feature Type", "Colour","Display"};
\r
427 private Object[][] data;
\r
429 public Object[][] getData()
\r
434 public int getColumnCount() {
\r
435 return columnNames.length;
\r
438 public Object[] getRow(int row)
\r
443 public int getRowCount() {
\r
444 return data.length;
\r
447 public String getColumnName(int col) {
\r
448 return columnNames[col];
\r
451 public Object getValueAt(int row, int col) {
\r
452 return data[row][col];
\r
455 public Class getColumnClass(int c) {
\r
456 return getValueAt(0, c).getClass();
\r
459 public boolean isCellEditable(int row, int col) {
\r
460 return col==0 ? false:true;
\r
463 public void setValueAt(Object value, int row, int col) {
\r
464 data[row][col] = value;
\r
465 fireTableCellUpdated(row, col);
\r
466 updateFeatureRenderer(data);
\r
470 class ColorRenderer extends JLabel
\r
471 implements TableCellRenderer {
\r
472 javax.swing.border.Border unselectedBorder = null;
\r
473 javax.swing.border.Border selectedBorder = null;
\r
475 public ColorRenderer() {
\r
476 setOpaque(true); //MUST do this for background to show up.
\r
479 public Component getTableCellRendererComponent(
\r
480 JTable table, Object color,
\r
481 boolean isSelected, boolean hasFocus,
\r
482 int row, int column) {
\r
483 Color newColor = (Color)color;
\r
484 setBackground(newColor);
\r
486 if (selectedBorder == null) {
\r
487 selectedBorder = BorderFactory.createMatteBorder(2,5,2,5,
\r
488 table.getSelectionBackground());
\r
490 setBorder(selectedBorder);
\r
492 if (unselectedBorder == null) {
\r
493 unselectedBorder = BorderFactory.createMatteBorder(2,5,2,5,
\r
494 table.getBackground());
\r
496 setBorder(unselectedBorder);
\r
499 setToolTipText("RGB value: " + newColor.getRed() + ", "
\r
500 + newColor.getGreen() + ", "
\r
501 + newColor.getBlue());
\r
507 class ColorEditor extends AbstractCellEditor
\r
508 implements TableCellEditor,
\r
510 Color currentColor;
\r
512 JColorChooser colorChooser;
\r
514 protected static final String EDIT = "edit";
\r
516 public ColorEditor() {
\r
517 //Set up the editor (from the table's point of view),
\r
518 //which is a button.
\r
519 //This button brings up the color chooser dialog,
\r
520 //which is the editor from the user's point of view.
\r
521 button = new JButton();
\r
522 button.setActionCommand(EDIT);
\r
523 button.addActionListener(this);
\r
524 button.setBorderPainted(false);
\r
525 //Set up the dialog that the button brings up.
\r
526 colorChooser = new JColorChooser();
\r
527 dialog = JColorChooser.createDialog(button,
\r
528 "Select new Colour",
\r
531 this, //OK button handler
\r
532 null); //no CANCEL button handler
\r
536 * Handles events from the editor button and from
\r
537 * the dialog's OK button.
\r
539 public void actionPerformed(ActionEvent e) {
\r
541 if (EDIT.equals(e.getActionCommand())) {
\r
542 //The user has clicked the cell, so
\r
543 //bring up the dialog.
\r
544 button.setBackground(currentColor);
\r
545 colorChooser.setColor(currentColor);
\r
546 dialog.setVisible(true);
\r
548 //Make the renderer reappear.
\r
549 fireEditingStopped();
\r
551 } else { //User pressed dialog's "OK" button.
\r
552 currentColor = colorChooser.getColor();
\r
556 //Implement the one CellEditor method that AbstractCellEditor doesn't.
\r
557 public Object getCellEditorValue() {
\r
558 return currentColor;
\r
561 //Implement the one method defined by TableCellEditor.
\r
562 public Component getTableCellEditorComponent(JTable table,
\r
564 boolean isSelected,
\r
567 currentColor = (Color)value;
\r