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 Object [][] originalData;
\r
39 final JInternalFrame frame;
\r
40 JScrollPane scrollPane = new JScrollPane();
\r
44 public FeatureSettings(AlignViewport av, final AlignmentPanel ap)
\r
48 fr = ap.seqPanel.seqCanvas.getFeatureRenderer();
\r
49 av.alignment.getSequences();
\r
50 frame = new JInternalFrame();
\r
51 frame.setContentPane(this);
\r
52 Desktop.addInternalFrame(frame, "Sequence Feature Settings", 400, 300);
\r
56 final JSlider transparency = new JSlider(0, 70, 0);
\r
57 transparency.addChangeListener(new ChangeListener()
\r
59 public void stateChanged(ChangeEvent evt)
\r
61 fr.setTransparency( (float) (100 - transparency.getValue()) / 100f);
\r
66 JPanel transPanel = new JPanel(new FlowLayout());
\r
67 transPanel.add(new JLabel("Transparency"));
\r
68 transPanel.add(transparency);
\r
70 //////////////////////////////////////////////
\r
71 //We're going to need those OK cancel buttons
\r
72 JPanel buttonPanel = new JPanel(new FlowLayout());
\r
73 JButton button = new JButton("OK");
\r
74 button.addActionListener(new ActionListener()
\r
76 public void actionPerformed(ActionEvent evt)
\r
80 frame.setClosed(true);
\r
82 catch (Exception exe)
\r
86 buttonPanel.add(button);
\r
87 button = new JButton("Cancel");
\r
88 button.addActionListener(new ActionListener()
\r
90 public void actionPerformed(ActionEvent evt)
\r
94 updateFeatureRenderer(originalData);
\r
95 frame.setClosed(true);
\r
97 catch (Exception exe)
\r
101 buttonPanel.add(button);
\r
103 button = new JButton("Load Colours");
\r
104 button.addActionListener(new ActionListener()
\r
106 public void actionPerformed(ActionEvent evt)
\r
111 buttonPanel.add(button);
\r
112 button = new JButton("Save Colours");
\r
113 button.addActionListener(new ActionListener()
\r
115 public void actionPerformed(ActionEvent evt)
\r
120 buttonPanel.add(button);
\r
122 this.setLayout(new BorderLayout());
\r
123 JPanel bigPanel = new JPanel(new BorderLayout());
\r
124 bigPanel.add(transPanel, BorderLayout.SOUTH);
\r
125 bigPanel.add(scrollPane, BorderLayout.CENTER);
\r
126 if(groupPanel!=null)
\r
127 bigPanel.add(groupPanel, BorderLayout.NORTH);
\r
129 add(bigPanel, BorderLayout.CENTER);
\r
130 add(buttonPanel, BorderLayout.SOUTH);
\r
135 void setTableData()
\r
137 if (fr.featureGroups == null)
\r
138 fr.featureGroups = new Hashtable();
\r
140 fr.featureGroups.clear();
\r
142 Vector allFeatures = new Vector();
\r
145 SequenceFeature sf;
\r
147 for (int i = 0; i < av.alignment.getHeight(); i++)
\r
149 features = av.alignment.getSequenceAt(i).getDatasetSequence().
\r
150 getSequenceFeatures();
\r
151 if (features == null)
\r
154 e = features.elements();
\r
155 while (e.hasMoreElements())
\r
157 sf = (SequenceFeature) e.nextElement();
\r
158 if(sf.getFeatureGroup()!=null
\r
159 && !fr.featureGroups.containsKey(sf.getFeatureGroup()))
\r
161 fr.featureGroups.put(sf.getFeatureGroup(), new Boolean(true));
\r
162 if(groupPanel==null)
\r
163 groupPanel = new JPanel();
\r
165 final JCheckBox check = new JCheckBox(sf.getFeatureGroup(), true);
\r
166 check.setFont(new Font("Serif", Font.BOLD, 12));
\r
167 check.addItemListener(new ItemListener()
\r
169 public void itemStateChanged(ItemEvent evt)
\r
171 if (fr.featureGroups.containsKey(check.getText()))
\r
173 fr.featureGroups.put(check.getText(),
\r
174 new Boolean(check.isSelected()));
\r
175 ap.seqPanel.seqCanvas.repaint();
\r
176 if (ap.overviewPanel != null)
\r
177 ap.overviewPanel.updateOverviewImage();
\r
182 groupPanel.add(check);
\r
184 if (!allFeatures.contains(sf.getType()))
\r
186 allFeatures.addElement(sf.getType());
\r
190 if(allFeatures.size()<1)
\r
193 { frame.setClosed(true); }
\r
194 catch (Exception ex){}
\r
196 JOptionPane.showInternalMessageDialog(
\r
197 Desktop.desktop, "No features have been added to this alignment!",
\r
198 "No Sequence Features", JOptionPane.WARNING_MESSAGE);
\r
203 int fSize = allFeatures.size();
\r
206 boolean originalExists = false;
\r
207 if(originalData!=null)
\r
208 originalExists = true;
\r
210 originalData = new Object[fSize][3];
\r
212 Object [][] data = new Object[fSize][3];
\r
213 for(int i=0; i<fSize; i++)
\r
215 type = allFeatures.elementAt(i).toString();
\r
216 Color col = fr.getColour(type);
\r
219 if(fr.featuresDisplayed!=null)
\r
220 data[i][2] = new Boolean(fr.featuresDisplayed.contains(type));
\r
222 data[i][2] = new Boolean(true);
\r
224 if(!originalExists)
\r
226 originalData[i][0] = type;
\r
227 originalData[i][1] = col;
\r
228 if (fr.featuresDisplayed != null)
\r
229 originalData[i][2] = new Boolean(fr.featuresDisplayed.contains(type));
\r
231 originalData[i][2] = new Boolean(true);
\r
234 ////////////////////////////////////
\r
235 //Now build the table
\r
236 table = new JTable(new FeatureTableModel(data));
\r
237 scrollPane.setViewportView(table);
\r
238 table.getTableHeader().setFont(new Font("Verdana", Font.PLAIN, 12));
\r
239 table.setFont(new Font("Verdana", Font.PLAIN, 12));
\r
240 table.setDefaultRenderer(Color.class,
\r
241 new ColorRenderer());
\r
243 table.setDefaultEditor(Color.class,
\r
244 new ColorEditor());
\r
246 table.getColumnModel().getColumn(0).setPreferredWidth(200);
\r
248 table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
\r
250 table.addMouseListener(new MouseAdapter()
\r
252 public void mousePressed(MouseEvent evt)
\r
254 selectedRow = table.rowAtPoint(evt.getPoint());
\r
258 table.addMouseMotionListener(new MouseMotionAdapter()
\r
260 public void mouseDragged(MouseEvent evt)
\r
262 int newRow = table.rowAtPoint(evt.getPoint());
\r
263 if(newRow!=selectedRow
\r
267 Object[] temp = new Object[3];
\r
268 temp[0] = table.getValueAt(selectedRow, 0);
\r
269 temp[1] = table.getValueAt(selectedRow, 1);
\r
270 temp[2] = table.getValueAt(selectedRow, 2);
\r
272 table.setValueAt(table.getValueAt(newRow, 0), selectedRow, 0);
\r
273 table.setValueAt(table.getValueAt(newRow, 1), selectedRow, 1);
\r
274 table.setValueAt(table.getValueAt(newRow, 2), selectedRow, 2);
\r
276 table.setValueAt(temp[0], newRow, 0);
\r
277 table.setValueAt(temp[1], newRow, 1);
\r
278 table.setValueAt(temp[2], newRow, 2);
\r
280 selectedRow = newRow;
\r
289 JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.getProperty(
\r
290 "LAST_DIRECTORY"), new String[] { "fc" },
\r
291 new String[] { "Sequence Feature Colours" }, "Sequence Feature Colours");
\r
292 chooser.setFileView(new jalview.io.JalviewFileView());
\r
293 chooser.setDialogTitle("Load Feature Colours");
\r
294 chooser.setToolTipText("Load");
\r
296 int value = chooser.showOpenDialog(this);
\r
298 if (value == JalviewFileChooser.APPROVE_OPTION)
\r
300 File file = chooser.getSelectedFile();
\r
304 InputStreamReader in = new InputStreamReader(new FileInputStream(
\r
307 jalview.binding.JalviewUserColours jucs = new jalview.binding.
\r
308 JalviewUserColours();
\r
309 jucs = (jalview.binding.JalviewUserColours) jucs.unmarshal(in);
\r
312 for (int i = 0; i < jucs.getColourCount(); i++)
\r
314 fr.setColour( jucs.getColour(i).getName(),
\r
315 new Color(Integer.parseInt( jucs.getColour(i).getRGB(), 16)));
\r
321 catch (Exception ex)
\r
323 System.out.println("Error loading User ColourFile\n" + ex);
\r
330 JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.getProperty(
\r
331 "LAST_DIRECTORY"), new String[] { "fc" },
\r
332 new String[] { "Sequence Feature Colours" }, "Sequence Feature Colours");
\r
333 chooser.setFileView(new jalview.io.JalviewFileView());
\r
334 chooser.setDialogTitle("Save Feature Colour Scheme");
\r
335 chooser.setToolTipText("Save");
\r
337 int value = chooser.showSaveDialog(this);
\r
339 if (value == JalviewFileChooser.APPROVE_OPTION)
\r
341 String choice = chooser.getSelectedFile().getPath();
\r
342 jalview.binding.JalviewUserColours ucs = new jalview.binding.JalviewUserColours();
\r
343 ucs.setSchemeName("Sequence Features");
\r
346 PrintWriter out = new PrintWriter(new OutputStreamWriter(
\r
347 new FileOutputStream(choice), "UTF-8"));
\r
349 Enumeration e = fr.featureColours.keys();
\r
350 while(e.hasMoreElements())
\r
354 jalview.binding.Colour col = new jalview.binding.Colour();
\r
355 col.setName(e.nextElement().toString());
\r
356 col.setRGB(jalview.util.Format.getHexString(
\r
357 fr.getColour(col.getName())));
\r
358 ucs.addColour(col);
\r
364 catch (Exception ex)
\r
366 ex.printStackTrace();
\r
372 public void updateFeatureRenderer(Object [][] data)
\r
374 fr.setFeaturePriority( data );
\r
377 if(ap.overviewPanel!=null)
\r
378 ap.overviewPanel.updateOverviewImage();
\r
381 int selectedRow =-1;
\r
384 /////////////////////////////////////////////////////////////////////////
\r
385 // http://java.sun.com/docs/books/tutorial/uiswing/components/table.html
\r
386 /////////////////////////////////////////////////////////////////////////
\r
387 class FeatureTableModel
\r
388 extends AbstractTableModel
\r
390 FeatureTableModel(Object[][] data)
\r
395 private String[] columnNames = {"Feature Type", "Colour","Display"};
\r
396 private Object[][] data;
\r
398 public Object[][] getData()
\r
403 public int getColumnCount() {
\r
404 return columnNames.length;
\r
407 public Object[] getRow(int row)
\r
412 public int getRowCount() {
\r
413 return data.length;
\r
416 public String getColumnName(int col) {
\r
417 return columnNames[col];
\r
420 public Object getValueAt(int row, int col) {
\r
421 return data[row][col];
\r
424 public Class getColumnClass(int c) {
\r
425 return getValueAt(0, c).getClass();
\r
428 public boolean isCellEditable(int row, int col) {
\r
429 return col==0 ? false:true;
\r
432 public void setValueAt(Object value, int row, int col) {
\r
433 data[row][col] = value;
\r
434 fireTableCellUpdated(row, col);
\r
435 updateFeatureRenderer(data);
\r
439 class ColorRenderer extends JLabel
\r
440 implements TableCellRenderer {
\r
441 javax.swing.border.Border unselectedBorder = null;
\r
442 javax.swing.border.Border selectedBorder = null;
\r
444 public ColorRenderer() {
\r
445 setOpaque(true); //MUST do this for background to show up.
\r
448 public Component getTableCellRendererComponent(
\r
449 JTable table, Object color,
\r
450 boolean isSelected, boolean hasFocus,
\r
451 int row, int column) {
\r
452 Color newColor = (Color)color;
\r
453 setBackground(newColor);
\r
455 if (selectedBorder == null) {
\r
456 selectedBorder = BorderFactory.createMatteBorder(2,5,2,5,
\r
457 table.getSelectionBackground());
\r
459 setBorder(selectedBorder);
\r
461 if (unselectedBorder == null) {
\r
462 unselectedBorder = BorderFactory.createMatteBorder(2,5,2,5,
\r
463 table.getBackground());
\r
465 setBorder(unselectedBorder);
\r
468 setToolTipText("RGB value: " + newColor.getRed() + ", "
\r
469 + newColor.getGreen() + ", "
\r
470 + newColor.getBlue());
\r
476 class ColorEditor extends AbstractCellEditor
\r
477 implements TableCellEditor,
\r
479 Color currentColor;
\r
481 JColorChooser colorChooser;
\r
483 protected static final String EDIT = "edit";
\r
485 public ColorEditor() {
\r
486 //Set up the editor (from the table's point of view),
\r
487 //which is a button.
\r
488 //This button brings up the color chooser dialog,
\r
489 //which is the editor from the user's point of view.
\r
490 button = new JButton();
\r
491 button.setActionCommand(EDIT);
\r
492 button.addActionListener(this);
\r
493 button.setBorderPainted(false);
\r
494 //Set up the dialog that the button brings up.
\r
495 colorChooser = new JColorChooser();
\r
496 dialog = JColorChooser.createDialog(button,
\r
497 "Select new Colour",
\r
500 this, //OK button handler
\r
501 null); //no CANCEL button handler
\r
505 * Handles events from the editor button and from
\r
506 * the dialog's OK button.
\r
508 public void actionPerformed(ActionEvent e) {
\r
510 if (EDIT.equals(e.getActionCommand())) {
\r
511 //The user has clicked the cell, so
\r
512 //bring up the dialog.
\r
513 button.setBackground(currentColor);
\r
514 colorChooser.setColor(currentColor);
\r
515 dialog.setVisible(true);
\r
517 //Make the renderer reappear.
\r
518 fireEditingStopped();
\r
520 } else { //User pressed dialog's "OK" button.
\r
521 currentColor = colorChooser.getColor();
\r
525 //Implement the one CellEditor method that AbstractCellEditor doesn't.
\r
526 public Object getCellEditorValue() {
\r
527 return currentColor;
\r
530 //Implement the one method defined by TableCellEditor.
\r
531 public Component getTableCellEditorComponent(JTable table,
\r
533 boolean isSelected,
\r
536 currentColor = (Color)value;
\r